package blackstar.performance.transform.instrutment;

import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.commons.LocalVariablesSorter;

/**
 * 性能修改代码抽象类，实现在方法的开始位置插入执行语句及方法结束的位置插入执行语句，类似于
 * doBegin();
 * try
 * {
 *    ...
 * }
 * finally
 * {
 *    doEnd();
 * }
 * 由于JVM汇编不支持finally语句，因此将如上转化成下面的处理过程：
 * 1.在方法开始位置加入doBegin
 * 2.在所有的return语句之前加入doEnd
 * 3.增加一个try...catch块，捕获所有的Exeption，调用doEnd并重新抛出Exception
 * @author RayWoo (ayufox@gmail.com)
 */
public abstract class AbstractPerformanceMethodAdapter extends
		LocalVariablesSorter implements Opcodes
{
	protected String className;
	protected String methodName;

	//JVM 汇编不支持finally语句，因此需要使用try ... catch住start-end来模拟finally语句
	private Label start = new Label();//代码开始位置
	private Label end = new Label();//代码结束位置

	public AbstractPerformanceMethodAdapter(String className,
			String methodName, int access, String desc, MethodVisitor mv)
	{
		super(access, desc, mv);

		this.className = className;
		this.methodName = methodName;
	}

	public void visitCode()
	{
		mv.visitCode();

		addBeginInvoke();
		
		mv.visitLabel(start);
	}

	public void visitInsn(int opcode)
	{
		if (opcode >= IRETURN && opcode <= RETURN)
		{
			addEndInvoke();
		}
		mv.visitInsn(opcode);
	}

	public void visitEnd()
	{
		mv.visitLabel(end);
		mv.visitTryCatchBlock(start, end, end, null);
		
		addExceptionInvoke();

		mv.visitInsn(ATHROW);
		mv.visitEnd();
	}

	private void addExceptionInvoke()
	{
		addEndInvoke();		
	}

	protected abstract void addEndInvoke();

	protected abstract void addBeginInvoke();
}
